From dcb731aad716c8a46a7e42ed4d414d7f1c7d9792 Mon Sep 17 00:00:00 2001 From: "kaf24@labyrinth.cl.cam.ac.uk" Date: Fri, 27 Aug 2004 12:28:34 +0000 Subject: [PATCH] bitkeeper revision 1.1159.56.1 (412f28f2oorf9i_6akPMKOUodxF7qg) Towards new device-interface setup code for the frontend drivers. Added a synchronous send-and-get-response call to the control interface API. Modified and extended the domain-controller messaging protocol. --- .../arch/xen/kernel/ctrl_if.c | 72 +++++++++++++++++-- .../drivers/xen/netfront/netfront.c | 9 +-- .../include/asm-xen/ctrl_if.h | 28 ++++++-- tools/python/xen/lowlevel/xu/xu.c | 8 +-- tools/python/xen/xend/server/netif.py | 5 +- .../hypervisor-ifs/io/domain_controller.h | 57 +++++++++++---- 6 files changed, 143 insertions(+), 36 deletions(-) diff --git a/linux-2.6.8.1-xen-sparse/arch/xen/kernel/ctrl_if.c b/linux-2.6.8.1-xen-sparse/arch/xen/kernel/ctrl_if.c index ef9958e3b7..40d29c70cb 100644 --- a/linux-2.6.8.1-xen-sparse/arch/xen/kernel/ctrl_if.c +++ b/linux-2.6.8.1-xen-sparse/arch/xen/kernel/ctrl_if.c @@ -201,7 +201,8 @@ static irqreturn_t ctrl_if_interrupt(int irq, void *dev_id, return IRQ_HANDLED; } -int ctrl_if_send_message_noblock( +int +ctrl_if_send_message_noblock( ctrl_msg_t *msg, ctrl_msg_handler_t hnd, unsigned long id) @@ -245,7 +246,8 @@ int ctrl_if_send_message_noblock( return 0; } -int ctrl_if_send_message_block( +int +ctrl_if_send_message_block( ctrl_msg_t *msg, ctrl_msg_handler_t hnd, unsigned long id, @@ -280,7 +282,59 @@ int ctrl_if_send_message_block( return rc; } -int ctrl_if_enqueue_space_callback(struct tq_struct *task) +/* Allow a reponse-callback handler to find context of a blocked requester. */ +struct rsp_wait { + ctrl_msg_t *msg; /* Buffer for the response message. */ + struct task_struct *task; /* The task that is blocked on the response. */ + int done; /* Indicate to 'task' that response is rcv'ed. */ +}; + +static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id) +{ + struct rsp_wait *wait = (struct rsp_wait *)id; + struct task_struct *task = wait->task; + + memcpy(wait->msg, msg, sizeof(*msg)); + wmb(); + wait->done = 1; + + wake_up_process(task); +} + +int +ctrl_if_send_message_and_get_response( + ctrl_msg_t *msg, + ctrl_msg_t *rmsg, + long wait_state) +{ + struct rsp_wait wait; + int rc; + + wait.msg = rmsg; + wait.done = 0; + wait.task = current; + + if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response, + (unsigned long)&wait, + wait_state)) != 0 ) + return rc; + + for ( ; ; ) + { + /* NB. Can't easily support TASK_INTERRUPTIBLE here. */ + set_current_state(TASK_UNINTERRUPTIBLE); + if ( wait.done ) + break; + schedule(); + } + + set_current_state(TASK_RUNNING); + return 0; +} + +int +ctrl_if_enqueue_space_callback( + struct tq_struct *task) { control_if_t *ctrl_if = get_ctrl_if(); @@ -299,7 +353,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task) return TX_FULL(ctrl_if); } -void ctrl_if_send_response(ctrl_msg_t *msg) +void +ctrl_if_send_response( + ctrl_msg_t *msg) { control_if_t *ctrl_if = get_ctrl_if(); unsigned long flags; @@ -327,7 +383,8 @@ void ctrl_if_send_response(ctrl_msg_t *msg) ctrl_if_notify_controller(); } -int ctrl_if_register_receiver( +int +ctrl_if_register_receiver( u8 type, ctrl_msg_handler_t hnd, unsigned int flags) @@ -361,7 +418,10 @@ int ctrl_if_register_receiver( return !inuse; } -void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd) +void +ctrl_if_unregister_receiver( + u8 type, + ctrl_msg_handler_t hnd) { unsigned long flags; diff --git a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c index 6e3d1ab6dc..71105776b2 100644 --- a/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6.8.1-xen-sparse/drivers/xen/netfront/netfront.c @@ -814,9 +814,10 @@ static void netif_driver_status_change( int err = 0; int i; - DPRINTK("> nr_interfaces=%d\n", status->nr_interfaces); + DPRINTK("> max_handle=%d\n", status->max_handle); - netctrl.interface_n = status->nr_interfaces; + /* XXX FIXME: Abuse of 'max_handle' as interface count. */ + netctrl.interface_n = status->max_handle; netctrl.connected_n = 0; for ( i = 0; i < netctrl.interface_n; i++ ) @@ -913,7 +914,7 @@ static int __init netif_init(void) cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED; cmsg.length = sizeof(netif_fe_driver_status_changed_t); st.status = NETIF_DRIVER_STATUS_UP; - st.nr_interfaces = 0; + st.max_handle = 0; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); @@ -999,7 +1000,7 @@ void netif_resume(void) cmsg.subtype = CMSG_NETIF_FE_DRIVER_STATUS_CHANGED; cmsg.length = sizeof(netif_fe_driver_status_changed_t); st.status = NETIF_DRIVER_STATUS_UP; - st.nr_interfaces = 0; + st.max_handle = 0; memcpy(cmsg.msg, &st, sizeof(st)); ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE); #endif diff --git a/linux-2.6.8.1-xen-sparse/include/asm-xen/ctrl_if.h b/linux-2.6.8.1-xen-sparse/include/asm-xen/ctrl_if.h index c90e010a03..ad1dde6464 100644 --- a/linux-2.6.8.1-xen-sparse/include/asm-xen/ctrl_if.h +++ b/linux-2.6.8.1-xen-sparse/include/asm-xen/ctrl_if.h @@ -37,7 +37,8 @@ typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long); * function returns. * 2. If @hnd is NULL then no callback is executed. */ -int ctrl_if_send_message_noblock( +int +ctrl_if_send_message_noblock( ctrl_msg_t *msg, ctrl_msg_handler_t hnd, unsigned long id); @@ -52,12 +53,23 @@ int ctrl_if_send_message_noblock( * function returns. * 2. If @hnd is NULL then no callback is executed. */ -int ctrl_if_send_message_block( +int +ctrl_if_send_message_block( ctrl_msg_t *msg, ctrl_msg_handler_t hnd, unsigned long id, long wait_state); +/* + * Send @msg to the domain controller. Block until the response is received, + * and then copy it into the provided buffer, @rmsg. + */ +int +ctrl_if_send_message_and_get_response( + ctrl_msg_t *msg, + ctrl_msg_t *rmsg, + long wait_state); + /* * Request a callback when there is /possibly/ space to immediately send a * message to the domain controller. This function returns 0 if there is @@ -65,7 +77,9 @@ int ctrl_if_send_message_block( * still be executed. If this function returns 1 then the callback /will/ be * executed when space becomes available. */ -int ctrl_if_enqueue_space_callback(struct tq_struct *task); +int +ctrl_if_enqueue_space_callback( + struct tq_struct *task); /* * Send a response (@msg) to a message from the domain controller. This will @@ -74,7 +88,9 @@ int ctrl_if_enqueue_space_callback(struct tq_struct *task); * 1. The @msg is copied and so can be freed after this function returns. * 2. The @msg may be the original request message, modified in-place. */ -void ctrl_if_send_response(ctrl_msg_t *msg); +void +ctrl_if_send_response( + ctrl_msg_t *msg); /* * Register a receiver for typed messages from the domain controller. The @@ -93,7 +109,9 @@ int ctrl_if_register_receiver( * Unregister a receiver for typed messages from the domain controller. The * handler (@hnd) will not be executed after this function returns. */ -void ctrl_if_unregister_receiver(u8 type, ctrl_msg_handler_t hnd); +void +ctrl_if_unregister_receiver( + u8 type, ctrl_msg_handler_t hnd); /* Suspend/resume notifications. */ void ctrl_if_suspend(void); diff --git a/tools/python/xen/lowlevel/xu/xu.c b/tools/python/xen/lowlevel/xu/xu.c index c1c171383e..f31d54b527 100644 --- a/tools/python/xen/lowlevel/xu/xu.c +++ b/tools/python/xen/lowlevel/xu/xu.c @@ -325,10 +325,10 @@ static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args) switch ( TYPE(xum->msg.type, xum->msg.subtype) ) { case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED): - P2C(blkif_fe_driver_status_changed_t, nr_interfaces, u32); + P2C(blkif_fe_driver_status_changed_t, max_handle, u32); break; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): - P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32); + P2C(netif_fe_driver_status_changed_t, max_handle, u32); break; } @@ -435,7 +435,7 @@ static PyObject *xu_message_get_payload(PyObject *self, PyObject *args) return dict; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): C2P(netif_fe_driver_status_changed_t, status, Int, Long); - C2P(netif_fe_driver_status_changed_t, nr_interfaces, Int, Long); + C2P(netif_fe_driver_status_changed_t, max_handle, Int, Long); return dict; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT): C2P(netif_fe_interface_connect_t, handle, Int, Long); @@ -630,7 +630,7 @@ static PyObject *xu_message_new(PyObject *self, PyObject *args) break; case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS_CHANGED): P2C(netif_fe_driver_status_changed_t, status, u32); - P2C(netif_fe_driver_status_changed_t, nr_interfaces, u32); + P2C(netif_fe_driver_status_changed_t, max_handle, u32); break; } diff --git a/tools/python/xen/xend/server/netif.py b/tools/python/xen/xend/server/netif.py index 1ba2169878..be8140da80 100755 --- a/tools/python/xen/xend/server/netif.py +++ b/tools/python/xen/xend/server/netif.py @@ -333,8 +333,9 @@ class NetifController(controller.SplitController): def recv_fe_driver_status_changed(self, msg, req): if not req: return msg = packMsg('netif_fe_driver_status_changed_t', - { 'status' : NETIF_DRIVER_STATUS_UP, - 'nr_interfaces' : len(self.devices) }) + { 'status' : NETIF_DRIVER_STATUS_UP, + ## FIXME: max_handle should be max active interface id + 'max_handle' : len(self.devices) }) self.writeRequest(msg) for dev in self.devices.values(): dev.attach_fe_device() diff --git a/xen/include/hypervisor-ifs/io/domain_controller.h b/xen/include/hypervisor-ifs/io/domain_controller.h index a7f3e4ee08..45090aca0f 100644 --- a/xen/include/hypervisor-ifs/io/domain_controller.h +++ b/xen/include/hypervisor-ifs/io/domain_controller.h @@ -76,6 +76,7 @@ typedef struct { #define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED 32 #define CMSG_BLKIF_FE_INTERFACE_CONNECT 33 #define CMSG_BLKIF_FE_INTERFACE_DISCONNECT 34 +#define CMSG_BLKIF_FE_INTERFACE_QUERY 35 /* These are used by both front-end and back-end drivers. */ #define blkif_vdev_t u16 @@ -87,7 +88,7 @@ typedef struct { * Notify a guest about a status change on one of its block interfaces. * If the interface is DESTROYED or DOWN then the interface is disconnected: * 1. The shared-memory frame is available for reuse. - * 2. Any unacknowledged messgaes pending on the interface were dropped. + * 2. Any unacknowledged messages pending on the interface were dropped. */ #define BLKIF_INTERFACE_STATUS_DESTROYED 0 /* Interface doesn't exist. */ #define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */ @@ -103,10 +104,13 @@ typedef struct { * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED: * Notify the domain controller that the front-end driver is DOWN or UP. * When the driver goes DOWN then the controller will send no more - * status-change notifications. When the driver comes UP then the controller - * will send a notification for each interface that currently exists. + * status-change notifications. * If the driver goes DOWN while interfaces are still UP, the domain * will automatically take the interfaces DOWN. + * + * NB. The controller should not send an INTERFACE_STATUS_CHANGED message + * for interfaces that are active when it receives an UP notification. We + * expect that the frontend driver will query those interfaces itself. */ #define BLKIF_DRIVER_STATUS_DOWN 0 #define BLKIF_DRIVER_STATUS_UP 1 @@ -114,11 +118,8 @@ typedef struct { /* IN */ u32 status; /* 0: BLKIF_DRIVER_STATUS_??? */ /* OUT */ - /* - * Tells driver how many interfaces it should expect to immediately - * receive notifications about. - */ - u32 nr_interfaces; /* 4 */ + /* Driver should query interfaces [0..max_handle]. */ + u32 max_handle; /* 4 */ } PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */ /* @@ -142,6 +143,18 @@ typedef struct { u32 handle; /* 0 */ } PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */ +/* + * CMSG_BLKIF_FE_INTERFACE_QUERY: + */ +typedef struct { + /* IN */ + u32 handle; /* 0 */ + /* OUT */ + u32 status; /* 4 */ + u16 evtchn; /* 8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */ + domid_t domid; /* 10: status != BLKIF_INTERFACE_STATUS_DESTROYED */ +} PACKED blkif_fe_interface_query_t; /* 12 bytes */ + /****************************************************************************** * BLOCK-INTERFACE BACKEND DEFINITIONS @@ -332,6 +345,7 @@ typedef struct { #define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED 32 #define CMSG_NETIF_FE_INTERFACE_CONNECT 33 #define CMSG_NETIF_FE_INTERFACE_DISCONNECT 34 +#define CMSG_NETIF_FE_INTERFACE_QUERY 35 /* * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED: @@ -355,10 +369,13 @@ typedef struct { * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED: * Notify the domain controller that the front-end driver is DOWN or UP. * When the driver goes DOWN then the controller will send no more - * status-change notifications. When the driver comes UP then the controller - * will send a notification for each interface that currently exists. + * status-change notifications. * If the driver goes DOWN while interfaces are still UP, the domain * will automatically take the interfaces DOWN. + * + * NB. The controller should not send an INTERFACE_STATUS_CHANGED message + * for interfaces that are active when it receives an UP notification. We + * expect that the frontend driver will query those interfaces itself. */ #define NETIF_DRIVER_STATUS_DOWN 0 #define NETIF_DRIVER_STATUS_UP 1 @@ -366,11 +383,8 @@ typedef struct { /* IN */ u32 status; /* 0: NETIF_DRIVER_STATUS_??? */ /* OUT */ - /* - * Tells driver how many interfaces it should expect to immediately - * receive notifications about. - */ - u32 nr_interfaces; /* 4 */ + /* Driver should query interfaces [0..max_handle]. */ + u32 max_handle; /* 4 */ } PACKED netif_fe_driver_status_changed_t; /* 8 bytes */ /* @@ -396,6 +410,19 @@ typedef struct { u32 handle; /* 0 */ } PACKED netif_fe_interface_disconnect_t; /* 4 bytes */ +/* + * CMSG_NETIF_FE_INTERFACE_QUERY: + */ +typedef struct { + /* IN */ + u32 handle; /* 0 */ + /* OUT */ + u32 status; /* 4 */ + u16 evtchn; /* 8: status == NETIF_INTERFACE_STATUS_CONNECTED */ + u8 mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */ + domid_t domid; /* 16: status != NETIF_INTERFACE_STATUS_DESTROYED */ +} PACKED netif_fe_interface_query_t; /* 18 bytes */ + /****************************************************************************** * NETWORK-INTERFACE BACKEND DEFINITIONS -- 2.30.2